package run.siyuan.rabbitmq.retry.message.service;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import run.siyuan.rabbitmq.retry.message.model.MessageRetryVo;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * @className: TtlTetsConsumer
 * @Description: TODO rabbitmq 补偿机制 抽象类
 * @author: siyuan
 * @date: 2022/5/13 3:05 PM
 */
@Slf4j
public abstract class AbstractCommonMessageService {


    /**
     * 发送消息
     *
     * @param retryVo
     */
    protected abstract void sendMessage(MessageRetryVo retryVo);


    /**
     * 构建消息补偿实体
     *
     * @param message
     * @return
     */
    protected MessageRetryVo buildMessageRetryInfo(Message message) {
        //如果头部包含补偿消息实体，直接返回
        Map<String, Object> messageHeaders = message.getMessageProperties().getHeaders();
        if (messageHeaders.containsKey("message_retry_info")) {
            Object retryMsg = messageHeaders.get("message_retry_info");
            if (Objects.nonNull(retryMsg)) {
                return JSONUtil.toBean(JSONUtil.parseObj(retryMsg), MessageRetryVo.class);
            }
        }
        //自动将业务消息加入补偿实体
        MessageRetryVo messageVo = new MessageRetryVo();
        messageVo.setBodyMsg(new String(message.getBody(), StandardCharsets.UTF_8));
        messageVo.setExchangeName(message.getMessageProperties().getReceivedExchange());
        messageVo.setRoutingKey(message.getMessageProperties().getReceivedRoutingKey());
        messageVo.setQueueName(message.getMessageProperties().getConsumerQueue());
        messageVo.setCreateTime(new Date());
        return messageVo;
    }

    /**
     * 准备执行
     *
     * @param messageVo
     */
    protected void prepareAction(MessageRetryVo messageVo) {
        if (messageVo.checkRetryCount(messageVo.getType())) {
            this.sendMessage(messageVo);
        } else {
            if (log.isWarnEnabled()) {
                log.warn("当前任务重试次数已经到达最大次数，业务数据：" + messageVo.toString());
            }
            doFailCallBack(messageVo);
        }
    }

    /**
     * 重试失败，回调服务
     *
     * @param messageVo
     */
    protected void doFailCallBack(MessageRetryVo messageVo) {
        try {
            saveRetryMessageInfo(messageVo);
        } catch (Exception e) {
            log.warn("执行失败回调异常，错误原因：{}", e.getMessage());
        }
    }

    /**
     * 将异常消息入库
     *
     * @param messageVo
     */
    protected void saveRetryMessageInfo(MessageRetryVo messageVo) {
        try {
            log.info("重试消息次数:{} message_retry_info:{}", messageVo.getCurrentRetryCount(), messageVo);
        } catch (Exception e) {
            log.error("将异常消息存储到mongodb失败，消息数据：" + messageVo.toString(), e);
        }
    }
}
